package Bio::Rambam::Proteomics::Experiment;
use Moose;
use namespace::autoclean;
use Data::Dumper;
use Bio::Rambam::Proteomics::Formats::OmssaFile;
#use Bio::Rambam::Proteomics::Protein;
#use Bio::Rambam::Proteomics::Psm;
#use Bio::Rambam::Proteomics::Quant;
#use Bio::Rambam::Proteomics::Formats::kkMzML;
#use Bio::Rambam::Proteomics::Quant::PsmQuantInfo;
#use Statistics::R;


#with 'Proteomics::experiment_filters';

has 'name'			=>	(is=>'rw',	isa=>'Str');
has 'proteins'		=>	(is=>'ro',	isa=>'HashRef[Bio::Rambam::Proteomics::Protein]'		,default=>sub{{}},clearer => 'clear_proteins',);
has 'psms'			=>	(is=>'ro',	isa=>'HashRef[Bio::Rambam::Proteomics::Psm]'			,default=>sub{{}},clearer => 'clear_psms',);
#has 'filters_stats'	=>	(is=>'rw',	isa=>'HashRef[Str]'						,default=>sub{{}},);





sub process_quant_info{
	my $self=shift;
	my %params=@_;
	
	die 'Quantitation method not defined\n' unless defined $params{'method'};
	die 'Spectra file not defined\n' unless defined $params{'mzml_file'};
	my $method=$params{'method'};
	my $mzMLfile=$params{'mzml_file'};
	my $ident_scan="";
	my $quant_scan="";
	my $quant_to_ident=0; #zero as default 
	$ident_scan=$params{ident_scan} if defined $params{ident_scan};
	$quant_scan=$params{quant_scan} if defined $params{quant_scan};
	$quant_to_ident=$params{quant_to_ident} if defined $params{quant_to_ident};
	
	if($method eq 'TMT2plex'){
		my @masses_label=(126,127);					####126.1283 127.1316
	}
	elsif($method eq 'TMT6plex'){
		my @masses_label=(126,127,128,129,130,131);	####126.1283 127.1316 128.1350 129.1383 130.1417 131.1387
		$self->load_quant_info(masses_label=>\@masses_label,mzml_file=>$mzMLfile,ident_scan=>$ident_scan,quant_scan=>$quant_scan,quant_to_ident=>$quant_to_ident);
		
	}
	elsif($method eq 'iTRAQ4plex'){
		my @masses_label=(114,115,116,117);
		
	}
	elsif($method eq  'iTRAQ8plex'){
		my @masses_label=(113,114,115,116,117,118,119,121);#
	}
	elsif($method eq  'LabelFree'){
		
	}
	elsif($method eq  'emPAI'){
		
	}
	else{
		die 'Quantitation method not defined\n';
	}
	
	
	
	
	
#	my %proteins=$self->get_proteins();
#	foreach my $protein_accession(keys %proteins){# First step: collect information from all psm's in the protein
#		my $protein=$proteins{$protein_accession};
#		next unless $protein->num_psms_ref();
#		my %psms_refs=%{$protein->psms_ref()};
#		foreach my $psms_ref(keys %psms_refs){
#				my $psm=${$self->psms}{$psms_ref};
#                my $itraq_info=$psm->itraq_info();
#                next unless $itraq_info->totalassign_unfiltered_psms_to_proteins_intensity;
#				$protein->set_itraq_info($psms_ref,$itraq_info);
#			
#		}
#		
#		$self->set_protein($protein);
#	}
#	my $R = Statistics::R->new();
#	foreach my $protein_accession(keys %proteins){# Second step: calculating statistics using R
#		my $protein=$proteins{$protein_accession};
#		next unless $protein->num_psms_ref();
#		$protein->set_itraq_stats($R);
#		
#		
#		
#	}
#	$R->stop();
}

sub _create_spectrum{
	my $spectrum_string=shift;
	my $spectrum=Bio::Rambam::Proteomics::Formats::MzMLSpectrum->new(text_mzML=>$spectrum_string);
	return $spectrum;
}

sub load_quant_info{
	my $self=shift;
	my %params=@_;
	my $method=$params{'method'};
	my $mzMLfile=$params{'mzml_file'};
	my $ident_scan="";
	my $quant_scan="";
	my $quant_to_ident=0; #zero as default 
	my @masses_label=@{$params{'masses_label'}};
	$ident_scan=$params{ident_scan} if defined $params{ident_scan};
	$quant_scan=$params{quant_scan} if defined $params{quant_scan};
	$quant_to_ident=$params{quant_to_ident} if defined $params{quant_to_ident};
	my $mzml_spec=Bio::Rambam::Proteomics::Formats::MzML->new(readfile=>$mzMLfile);
	#print Dumper %params;
	open FILE,"<",$mzMLfile;
	my %indexes=%{$mzml_spec->parse_indexes};
	
	foreach my $psm(keys %{$self->psms}){
		my $index=(split /\|/,${$self->psms}{$psm}->identifier)[3];
		next unless ${$self->psms}{$psm}->filterstatus eq 'noFilter';#############solo info cuantitativa de las psms sin filtrar
		
		#### solo psms con 1 unica proteina asignada
		if (${$self->psms}{$psm}->peptide->number_proteins >1){
			#${$self->psms}{$psm}->filterstatus('scoreFilter');
			#next;
		}
		
		
		seek(FILE, $indexes{$index}, 0);
		my $text;
		while(<FILE>){
			$text.=$_;
			last if /\<\/spectrum\>/;
		}
		my $spectrum=_create_spectrum($text);
		#print $spectrum->fragmentation,"\n";
		#print $ident_scan,"\n";
		#exit;
		if($spectrum->fragmentation eq $ident_scan){
			#print "aquiiii\n";exit;
			seek(FILE, $indexes{$quant_to_ident+$index}, 0);
			my $text2;
			while(<FILE>){
				$text2.=$_;
				last if /\<\/spectrum\>/;
			}
			my $spectrum2=_create_spectrum($text2);
			unless((defined $spectrum->precursor_mz)and(defined $spectrum2->precursor_mz)){#Esto es importante
				${$self->psms}{$psm}->filterstatus('non-existentPrecursor');
				next;
				unless($spectrum->precursor_mz==$spectrum2->precursor_mz){
					${$self->psms}{$psm}->filterstatus('not-fittingPrecursorMasses');
					next;
				}
			}
		
			$spectrum2->translate_spectra;
			my @int=@{$spectrum2->array_int_translated};
			my @mz =@{$spectrum2->array_mz_translated};
			my %quants;
			my %quants2;
			foreach my $mass_label(@masses_label){
				$quants{$mass_label}=0;
				for my $i (0..$#mz){
					if((($mass_label-0.5)<=$mz[$i])and($mz[$i]<($mass_label+0.5))){
						$quants{$mass_label}=$quants{$mass_label}+$int[$i];
						$quants2{$mass_label}=$quants{$mass_label}+$int[$i];
					}
				}
			}
			my $quant_info=Bio::Rambam::Proteomics::Quant::PsmQuantInfo->new(quantInfo=>\%quants);
			my $quant_info_prot=Bio::Rambam::Proteomics::Quant::PsmQuantInfo->new(quantInfo=>\%quants2);
			
			unless($quant_info->total_intensity >0){
				${$self->psms}{$psm}->filterstatus('no-quantInfo');
			}
			
			${$self->psms}{$psm}->quant_info($quant_info);
			my @protein_accessions=@{${$self->psms}{$psm}->peptide->protein_accessions};
			
			foreach my $prot(@protein_accessions){
				${$self->proteins}{$prot}->set_quant_info($psm,$quant_info);
			}
			
			
			
#			my $quants_tag="";
#			foreach my $quant(sort { $a <=> $b } keys %quants){proteins
#				$quants_tag=$quants_tag."|".$quants{$quant};
#			}
#			######Aqui va la recoleccion de lo cuantificdo
#			if (($quants_tag eq '|0|0|0|0|0|0')or($quants_tag eq "")){
#				$psms{$psm}->filterstatus("no-quantInfo");
#				next;
#			};
#			$psms{$psm}->quant_info($quants_tag);
		}
		elsif($spectrum->fragmentation eq $quant_scan	){
			${$self->psms}{$psm}->filterstatus('wrongFragmentation');
			next;
		}
		######  Filtro a saco
		# OMSSA score
#		my @scores=@{$psms{$psm}->peptide->scores};
#		foreach my $score(@scores){
#			my $name=$score->name;
#			if($name eq 'omssa_evalue'){
#				if($score->value>0.01){
#					${$self->psms}{$psm}->filterstatus('scoreFilter');
#					next;
#				}
#			}
#		}
	}
	close FILE;
}



sub assign_unfiltered_psms_to_proteins{
	my $self=shift;
	my %psms=$self->get_psms();
	my %unfiltered_psms;
	foreach my $identifier(keys %psms){
		my $psm=$psms{$identifier};
		next unless $psm->filterstatus eq 'noFilter';
		my @proteins=$psm->peptide->get_proteins();
		foreach my $protein_accession(@proteins){
			if(defined ${$self->proteins}{$protein_accession}){
				my $protein=${$self->proteins}{$protein_accession};
				$protein->set_psms_ref($identifier);
				$self->set_protein($protein);
			}
		}
	}
	
}


sub get_total_psms_number{
	my $self=shift;
	my $total_psms_number=scalar keys %{$self->psms};
}

sub get_unfiltered_psms{
	my $self=shift;
	my %psms=$self->get_psms();
	my %unfiltered_psms;
	foreach my $identifier(keys %psms){
		my $psm=$psms{$identifier};
		next if $psm->filterstatus;
		$unfiltered_psms{$identifier}=$psm;
	}
	return %unfiltered_psms;
}

sub get_unfiltered_proteins{
	my $self=shift;
	my %proteins=$self->get_proteins();
	my %unfiltered_proteins;
	foreach my $identifier(keys %proteins){
		my $protein=$proteins{$identifier};
		next if $protein->num_psms_ref==0;
		$unfiltered_proteins{$identifier}=$protein;
	}
	return %unfiltered_proteins;
}


sub add_peptide_to_psm{
	my $self=shift;
	my $peptide = shift;
	my $identifier=$peptide->identifier();
	
	if(defined ${$self->psms}{$identifier})	{
		my $psm=${$self->psms}{$identifier};
		$psm->peptide($peptide);
		${$self->psms}{$identifier}=$psm;
	}
	else{
		my $psm=Bio::Rambam::Proteomics::Psm->new(identifier=>$identifier,peptide=>$peptide);
		${$self->psms}{$identifier}=$psm;
	}
}

sub get_peptides{
	my $self=shift;
	my @peptides;
	foreach my $identifier(keys %{$self->psms}){
		my $psm=${$self->psms}{$identifier};
		my $peptide=$psm->peptide;
		push @peptides,$peptide if defined $peptide;
	}
	return @peptides;
}

sub set_protein{
	my $self=shift;
	my $protein = shift;
	${$self->proteins}{$protein->accession}=$protein;
}

sub get_proteins{
	my $self=shift;
	my %proteins=%{$self->proteins};
	return %proteins;
}

sub get_psms{
	my $self=shift;
	my %psms=%{$self->psms};
	return %psms;
}


sub process_omssa_csv_files{
	my $self=shift;
	my $file_names_ref=shift;
	foreach my $filename(@$file_names_ref){
		my $omssa_file=Bio::Rambam::Proteomics::Formats::OmssaFile->new(file=>$filename);
		my ($peps_ref,$prots_ref)=$omssa_file->parse();
		foreach my $pep(@$peps_ref){
			$self->add_peptide_to_psm($pep);
		}
		foreach my $prot_key(keys %$prots_ref){
			$self->set_protein($$prots_ref{$prot_key});
		}
		print "File $filename read\n";
	}
	
}

sub extract_itraq_info{
	my $self=shift;
	my $mgf_files=shift;

	my %mgf_info;
	my %mgf_couples;
	my $number_of_couples=0;
	
	foreach my $mgf_file(@$mgf_files){
		print $mgf_file,"\n";
		open MGF,"<",$mgf_file;
		local $/="END IONS";

		while(<MGF>){
			my @spec_lines=split /\n/,$_;
			my $spec_title='';
			my $itraq_mgf_data='';
			my $fragmentation_mgf_data='';
			my $itraq_couple='';
			my $scan='';
			
			
			foreach(@spec_lines){
				$spec_title=$1 if $_=~s/^TITLE\=(.+)//;
				$scan=$1 if $_=~s/^SCAN\=(.+)//;
				$itraq_mgf_data=$1 if $_=~s/^USER00\=(.+)//;
				$fragmentation_mgf_data=$1 if $_=~s/^USER01\=(.+)//;
				$itraq_couple=$1 if $_=~s/^USER02\=(.+)//;
				if ($_=~/^\d/){
					$mgf_info{$spec_title}{'itraq'}=$itraq_mgf_data;
					$mgf_info{$spec_title}{'fragmentation'}=$fragmentation_mgf_data;
					$mgf_info{$spec_title}{'scan'}=$scan;
					if($itraq_couple){
						$number_of_couples++;
						$mgf_couples{$itraq_couple}=$number_of_couples;
						$mgf_couples{$spec_title}=$number_of_couples;
					}
					last;
				}
			}
		}
		close MGF;
	}
	#### iTRAQ info
	foreach my $identifier(keys %mgf_info){
		my $fragmentation	=$mgf_info{$identifier}{'fragmentation'};
		my $itraq			=$mgf_info{$identifier}{'itraq'};
		my $scan			=$mgf_info{$identifier}{'scan'};
		my @itraq_data=split "\\|",$itraq;
		my %itraq_hash=(
			'int114'=>($itraq_data[0]*1.1956),######facotes correccion a lo BRUTO!!!!!
			'int115'=>($itraq_data[1]*0.9615),
			'int116'=>($itraq_data[2]*0.9060),
			'int117'=>($itraq_data[3]*0.9807),
		);
		if(defined ${$self->psms}{$identifier}){
			my $psm=${$self->psms}{$identifier};
			$psm->set_itraq_info(%itraq_hash);
			$psm->index($scan);
			$psm->fragmentation($fragmentation);
			${$self->psms}{$identifier}=$psm;
		}
	}
	#### couples info
	my %multiple_groups;
	foreach my $identifier(keys %mgf_couples){
		next unless defined ${$self->psms}{$identifier};
		my $group=$mgf_couples{$identifier};
		if(defined $multiple_groups{$group}){
			$multiple_groups{$group}++;
		}
		else{
			$multiple_groups{$group}=1;
		}
	}
	foreach my $identifier(keys %mgf_couples){
		my $group=$mgf_couples{$identifier};
		next unless defined ${$self->psms}{$identifier};
		next unless $multiple_groups{$group}>1;
		my $psm=${$self->psms}{$identifier};
		$psm->group($group);
		${$self->psms}{$identifier}=$psm;
	}


}









__PACKAGE__->meta->make_immutable;
